//
// This file is part of the aMule Project.
//
// Copyright (c) 2003-2006 aMule Team ( admin@amule.org / http://www.amule.org )
// Copyright (c) 2002 Merkur ( devs@emule-project.net / http://www.emule-project.net )
//
// Any parts of this program derived from the xMule, lMule or eMule project,
// or contributed by third-party developers are copyrighted by their
// respective authors.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
//

#include "SafeFile.h"	// Interface declarations.
#include "UInt128.h"	// Needed for CUInt128

#include <algorithm>    // Needed for std::min

using namespace std;

#define CHECK_BOM(size, x) ((size >= 3)  && (x[0] == (char)0xEF) && (x[1] == (char)0xBB) && (x[2] == (char)0xBF))

const char BOMHeader[3] = {0xEF, 0xBB, 0xBF};

///////////////////////////////////////////////////////////////////////////////
// CFileDataIO


CFileDataIO::~CFileDataIO()
{
}


bool CFileDataIO::Eof() const
{
	return GetPosition() >= GetLength();
}


void CFileDataIO::Read(void *buffer, size_t count) const
{
	//MULE_VALIDATE_PARAMS(buffer, wxT("Attempting to write to NULL buffer."));

	// Check that we read everything we wanted.
	if (doRead(buffer, count) == count) {
		return;
	}

	// To reduce potential system calls, we only do EOF checks when reads fail.
	//if (Eof()) {
	//	throw CEOFException(wxT("Attempt to read past end of file."));
	//} else {
	//	throw CIOFailureException(wxT("Read error, failed to read from file."));
	//}
}


void CFileDataIO::Write(const void* buffer, size_t count)
{
	//MULE_VALIDATE_PARAMS(buffer, wxT("Attempting to read from NULL buffer."));

	if (doWrite(buffer, count) != count) {
		//throw CIOFailureException(wxT("Write error, failed to write to file."));
	}
}


uint64 CFileDataIO::Seek(sint64 offset, int from) const
{
	sint64 newpos = 0;
	switch (from) {
		case 0:
			//start
			newpos = offset;
			break;
		case 1:
			// current pos
			newpos = GetPosition() + offset;
			break;
		case 2:
			//end
			newpos = GetLength() + offset;
			break;
			
		default:
			;//MULE_VALIDATE_PARAMS(false, wxT("Invalid seek-mode specified."));
	}
	
	//MULE_VALIDATE_PARAMS(newpos >= 0, wxT("Position after seeking would be less than zero!"));

	sint64 result = doSeek(newpos);
	//MULE_VALIDATE_STATE(result >= 0, wxT("Seeking resulted in invalid offset."));
	//MULE_VALIDATE_STATE(result == newpos, wxT("Target position and actual position disagree."));
	
	return result;
}


uint8 CFileDataIO::ReadUInt8() const
{
	uint8 value = 0;
	Read(&value, 1);

	return value;
}


uint16 CFileDataIO::ReadUInt16() const
{
	uint16 value = 0;
	Read(&value, 2);
	
	return value;
}


uint32 CFileDataIO::ReadUInt32() const
{
	uint32 value = 0;
	Read(&value, 4);
	
	return value;
}


CUInt128 CFileDataIO::ReadUInt128() const
{
	CUInt128 value;
	uint32* data = (uint32*)value.getDataPtr();
	for (int i = 0; i < 4; i++) {
		data[i] = ReadUInt32();
	}

	return value;
}


void CFileDataIO::WriteUInt8(uint8 value)
{
	Write(&value, 1);
}


void CFileDataIO::WriteUInt16(uint16 value)
{
	// ENDIAN_SWAP_I_16(value);
	
	Write(&value, 2);
}


void CFileDataIO::WriteUInt32(uint32 value)
{
	// ENDIAN_SWAP_I_32(value);
	
	Write(&value, 4);
}


void CFileDataIO::WriteUInt128(const CUInt128& value)
{
	for (int i = 0; i < 4; i++) {
		WriteUInt32(value.get32BitChunk(i));
	}
}

















